package com._4pd.demo.demo;

import freemarker.template.*;
import freemarker.template.Version;
import io.fabric8.kubernetes.api.model.GenericKubernetesResource;
import io.fabric8.kubernetes.api.model.apiextensions.v1.CustomResourceDefinition;
import io.fabric8.kubernetes.client.*;
import io.fabric8.kubernetes.client.dsl.Resource;
import io.fabric8.kubernetes.client.dsl.base.ResourceDefinitionContext;
import com._4pd.demo.demo.crd.AiOperator;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.function.UnaryOperator;

import static io.fabric8.kubernetes.client.Watcher.Action.DELETED;

public class Main {
    public static void main(String[] args) throws IOException, TemplateException {

        KubernetesClient client = new KubernetesClientBuilder().build();
        // 注册crd
        CustomResourceDefinition crd = client.apiextensions().v1()
                .customResourceDefinitions()
                .load(new File("target/classes/META-INF/fabric8/aioperator.demo.ai.operator-v1.yml"))
                .get();
        Resource<CustomResourceDefinition> resource = client.apiextensions().v1().customResourceDefinitions().resource(crd);
        if (resource.isReady()) {
            System.out.println("crd is ready");
            resource.delete();
        } else {
            System.out.println("crd is not ready,create it!");
        }
        resource.create();

        client.genericKubernetesResources(new ResourceDefinitionContext.Builder()
                .withKind("Workflow")
                .withGroup("argoproj.io")
                .withVersion("v1alpha1")
                .withNamespaced(true)
                .build()).watch(new Watcher<GenericKubernetesResource>() {
            @Override
            public void eventReceived(Action action, GenericKubernetesResource resource) {
                //workflow => aioperator => status
                switch (action){
                    case DELETED:
                        Resource<AiOperator> task = client.resources(AiOperator.class).inNamespace("airflow").withName(resource.getMetadata().getLabels().get("task"));
                        task.edit(new UnaryOperator<AiOperator>() {
                            @Override
                            public AiOperator apply(AiOperator aiOperator) {
                                aiOperator.getMetadata().getLabels().put("finish","true");
                                return aiOperator;
                            }
                        });
                        break;
                }
            }

            @Override
            public void onClose(WatcherException cause) {

            }
        });
        // 监听AiOperator
        client.genericKubernetesResources(new ResourceDefinitionContext.Builder()
                .withKind("AiOperator")
                .withPlural("aioperator")
                .withVersion("v1")
                .withGroup("demo.ai.operator")
                .withNamespaced(true)
                .build()).watch(new Watcher<GenericKubernetesResource>() {
            @Override
            public void eventReceived(Action action, GenericKubernetesResource resource) {
                try {
                    System.out.println(action);
                    if (action.equals(Action.ADDED)) {
                        System.out.println("CREATE!");
                        Map<String,Object> data = new HashMap<>();
                        //data.put("run_conf", JSON.toJSONString(spec));
                        data.put("name",resource.getMetadata().getName()+"aioperator-"+(int)(Math.random()*100));
                        data.put("run_conf", "spec");
//                        data.put("run_conf", JSON.toJSONString(resource.getAdditionalProperties().get("spec")));
                        Configuration cfg = new Configuration(new Version("2.3.23"));
                        cfg.setDirectoryForTemplateLoading(new File("src/main/resources"));
                        cfg.setDefaultEncoding("UTF-8");
                        Template template = cfg.getTemplate("freemarker/init-table.yaml");
                        StringWriter out = new StringWriter();
                        template.process(data, out);
                        out.flush();

                        Resource<GenericKubernetesResource> cr = client.genericKubernetesResources(new ResourceDefinitionContext.Builder()
                                .withKind("Workflow")
                                .withGroup("argoproj.io")
                                .withVersion("v1alpha1")
                                .withNamespaced(true)
                                .build()).load(new StringBufferInputStream(out.getBuffer().toString()));
                        GenericKubernetesResource genericResource = cr.create();

                        // 给crd 关联 子任务 信息
                        client.resource(resource).edit(genericKubernetesResource -> {
                            genericKubernetesResource.getMetadata().getLabels().put("task", String.valueOf(data.get("name")));
                            return genericKubernetesResource;
                        });
                        // 给 子任务 关联 crd 信息
                        client.resource(genericResource).edit(genericKubernetesResource -> {
                            genericKubernetesResource.getMetadata().getLabels().put("task",resource.getMetadata().getName());
                            return genericKubernetesResource;
                        });
                    }else if (action.equals(DELETED)){
                        Resource<GenericKubernetesResource> resourceResource = client.genericKubernetesResources(new ResourceDefinitionContext.Builder()
                                .withKind("Workflow")
                                .withGroup("argoproj.io")
                                .withVersion("v1alpha1")
                                .withNamespaced(true)
                                .build()).inNamespace("airflow").withName(resource.getMetadata().getLabels().get("task"));
                        resourceResource.delete();
                    }else {
                        System.out.println("OTHER!");
                    }
                    System.out.println("END!");
                } catch (Exception e) {
                    e.printStackTrace();
                    throw new RuntimeException(e);
                }
            }

            @Override
            public void onClose(WatcherException cause) {
            }
        });
    }
}